from uuid import uuid4
import datetime
import math
import os

from rest_framework import serializers

from .models import Mission
from apps.gateway.models import Sensor, Gateway
from apps.manageFile.models import MFileModel
from util.exception import ValidationError
from django.conf import settings

misson_numbers = [
    settings.REBOOT_GATEWAY,
    settings.REBOOT_SENSOR,
    settings.UPDATE_GATEWAY,
    settings.UPDATE_SENSOR,
    settings.READ_GATEWAY,
    settings.READ_SENSOR,
    settings.UPLOAD_DEPLOY,
    settings.UPLOAD_LOG,
    settings.DOWN_SCRIPT,
    settings.DOWN_DEPLOY,
    settings.GET_DATA,
    settings.MAIN_GATEWAY,
    settings.CONFIG_GATEWAY,
    settings.AGREEMENT_GATEWAY,
    settings.POWEROFF,
    settings.QUERY_SIM
]

STATE_NUMBER = {
    -1: "任务失败",
    0: "任务进行",
    1: "任务成功"
}


class MissionSerializerSearch(serializers.Serializer):
    mission_number = serializers.ChoiceField(allow_null=True, choices=misson_numbers)
    gateway_id = serializers.CharField(allow_null=True)
    sensor_number = serializers.IntegerField(allow_null=True)
    state = serializers.ChoiceField(allow_null=True, choices=list(STATE_NUMBER.keys()))
    start_date = serializers.DateTimeField(allow_null=True)
    end_date = serializers.DateTimeField(allow_null=True)
    order = serializers.IntegerField(allow_null=True)


class MissionSerializerListList(serializers.ModelSerializer):
    class Meta:
        model = Mission
        fields = "__all__"


class MissionSerializercreate(serializers.Serializer):
    key_list = serializers.ListField(max_length=32, allow_null=False)
    mission_number = serializers.ChoiceField(allow_null=False, choices=misson_numbers)
    mission_parameter = serializers.CharField(max_length=2000, allow_null=True)
    sensor_list = serializers.ListField(allow_null=True)
    end_date = serializers.DateTimeField(allow_null=True)

    def validate(self, attrs):
        return attrs

    def create(self, validated_data):
        mission_parameter = validated_data.get("mission_parameter")
        mfile = MFileModel.objects.filter(id=mission_parameter).first()
        mission_parameter = mfile.filepath if mfile else mission_parameter
        mission_number = validated_data.get("mission_number")
        key_list = validated_data.get("key_list")
        sensor_list = validated_data.get("sensor_list")
        end_date = validated_data.get("end_date")
        mission_list = []
        mission_id_list = []
        if mission_number != settings.GET_DATA:
            for key in key_list:
                gateway = Gateway.objects.filter(key=key).first()
                connected = int(gateway.state)
                if sensor_list:
                    sensors = Sensor.objects.filter(id__in=sensor_list).all()
                    for sensor in sensors:
                        id = str(uuid4()).replace("-", "")
                        if not connected:
                            obj = Mission(id=id, key=key, gateway_id=gateway.gateway_id, sensor_id=sensor.id,
                                          sensor_number=sensor.number,
                                          mission_number=mission_number, file_path=mission_parameter, state=-1,
                                          failed_reason="网关离线")
                        else:
                            obj = Mission(id=id, key=key, gateway_id=gateway.gateway_id, sensor_id=sensor.id,
                                          sensor_number=sensor.number,
                                          mission_number=mission_number, file_path=mission_parameter)
                            mission_id_list.append(id)
                        mission_list.append(obj)
                else:
                    if mission_number == settings.UPDATE_GATEWAY:
                        if gateway.is_tac31:
                            mission_number = settings.MAIN_GATEWAY
                            validated_data["mission_number"] = settings.MAIN_GATEWAY
                    id = str(uuid4()).replace("-", "")
                    if not connected and mission_number != settings.QUERY_SIM:
                        if gateway.is_tac31:
                            obj = Mission(id=id, key=key, gateway_id=gateway.gateway_id, mission_number=mission_number,
                                          state=0, file_path=mission_parameter, failed_reason="网关离线")
                        else:
                            obj = Mission(id=id, key=key, gateway_id=gateway.gateway_id, mission_number=mission_number,
                                          state=-1, file_path=mission_parameter, failed_reason="网关离线")
                    else:
                        obj = Mission(id=id, key=key, gateway_id=gateway.gateway_id, mission_number=mission_number,
                                      file_path=mission_parameter)
                        mission_id_list.append(id)
                    mission_list.append(obj)
            if mission_list:
                Mission.objects.bulk_create(mission_list)
            else:
                raise ValidationError(80003)
        else:
            id = str(uuid4()).replace("-", "")
            sensor_id_list = []
            s = ""
            if end_date:
                description = "".join([end_date.strftime("%y%m%d"), ",", end_date.strftime("%H")])
            else:
                description = ""
            for key in key_list:
                gateway = Gateway.objects.filter(key=key).first()
                if sensor_list:
                    sensors = Sensor.objects.filter(id__in=sensor_list).all()
                    for sensor in sensors:
                        sensor_id_list.append(sensor.number)
                    for number in sensor_id_list:
                        s += (str(number) + ",")
                description = "".join([s, "/", description])
                connected = int(gateway.state)
                if not connected:
                    Mission.objects.create(id=id, key=key, gateway_id=gateway.gateway_id, mission_number=mission_number,
                                           state=-1)
                else:
                    Mission.objects.create(id=id, key=key, gateway_id=gateway.gateway_id, mission_number=mission_number,
                                           description=description)
                    mission_id_list.append(id)
        return {
            "mission_id_list": mission_id_list,
        }


class MissionLogSerializercreate(serializers.Serializer):
    key = serializers.CharField(max_length=32, allow_null=False)
    mission_number = serializers.ChoiceField(allow_null=False, choices=misson_numbers)
    sensor_id = serializers.CharField(allow_null=True)
    start_date = serializers.DateTimeField(allow_null=True)
    end_date = serializers.DateTimeField(allow_null=True)

    def validate(self, attrs):
        datetime_list = []
        start_date = attrs.get("start_date")
        end_date = attrs.get("end_date")
        gap_seconds = (end_date - start_date).seconds
        gap_hours = math.floor(gap_seconds / 3600)
        for i in range(gap_hours + 1):
            datetime_list.append(start_date + datetime.timedelta(hours=i))
        attrs["datetime_list"] = datetime_list
        return attrs

    def create(self, validated_data):
        mission_id_list = []
        missions = []
        key = validated_data.get("key")
        mission_number = validated_data.get("mission_number")
        sensor_id = validated_data.get("sensor_id")
        datetime_list = validated_data.pop("datetime_list")
        gateway = Gateway.objects.filter(key=key).first()
        sensor = Sensor.objects.filter(id=sensor_id).first()
        connected = int(gateway.state)
        for datetime_example in datetime_list:
            file_head = datetime_example.strftime("%y/%m/%d/")
            if sensor_id:
                file_body = "".join(
                    [str(gateway.gateway_id), "/", str(sensor.number), "/", datetime_example.strftime("%H")])
            else:
                file_body = "".join([str(gateway.gateway_id), "/", datetime_example.strftime("%H")])
            file_path = "".join([settings.LOG_FILE_PATH, "/", file_head, file_body])
            description = "".join([datetime_example.strftime("%y%m%d"), ",", datetime_example.strftime("%H")])
            mission_id = str(uuid4()).replace("-", "")
            if not connected:
                obj = Mission(id=mission_id, key=key, gateway_id=gateway.gateway_id, sensor_id=sensor_id,
                              sensor_number=sensor.number, state=-1,
                              mission_number=mission_number, file_path=file_path, description="设备不在线", is_delete=False)
            else:
                obj = Mission(id=mission_id, key=key, gateway_id=gateway.gateway_id, sensor_id=sensor_id,
                              sensor_number=sensor.number,
                              mission_number=mission_number, file_path=file_path, description=description,
                              is_delete=False)
                mission_id_list.append(mission_id)
            missions.append(obj)
        Mission.objects.bulk_create(missions)
        return mission_id_list


class MissionRemoveSerializercreate(serializers.Serializer):
    mission_id = serializers.CharField(max_length=32, allow_null=False)

    def validate__mission_id(self, obj):
        mission = Mission.objects.filter(id=obj)
        if not mission:
            raise ValidationError(80001)
        return obj

    def remove(self, data):
        mission_id = data["mission_id"]
        mission = Mission.objects.filter(id=mission_id).first()
        file_path = mission.file_path
        if os.path.exists(file_path):
            os.remove(file_path)
        Mission.objects.filter(id=mission_id).delete()
